package cn.antia.cep.db.hibernate.dao;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.*;

import org.hibernate.criterion.*;
import org.hibernate.*;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import cn.antia.cep.common.SysExceptionTool;
import cn.antia.cep.db.DBException;

public class HibeGenericDAO extends HibernateDaoSupport {
    /**
     * batchCreate
     *
     * @param objectList List
     * @throws DBException this cn.antia.uums.server.core.dao.DAOInterface method
     */
    public void batchCreate(List objectList) throws DBException {
        try {
            this.getHibernateTemplate().saveOrUpdateAll(objectList);
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
    }

    /**
     * batchRemove
     *
     * @param idArray String[]
     * @throws DBException Implement this cn.antia.uums.server.core.dao.DAOInterface method
     */
    public void batchRemove(int[] idArray) throws DBException {
        try {
            if (idArray != null && idArray.length > 0) {
                for (int i = 0, j = idArray.length; i < j; i++) {
                    int id = idArray[i];
                    this.remove(id);
                }
            }
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
    }

    /**
     * create
     *
     * @param o Object
     * @throws DBException Implement this cn.antia.uums.server.core.dao.DAOInterface method
     */
    public void create(Object o) throws DBException {
        try {
            this.getHibernateTemplate().save(o);
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
    }

    /**
     * find
     * 统一的根据查找记录DAO方法
     *
     * @param o       Object
     * @param isEqual boolean
     * @return List
     * @throws DBException Implement this cn.antia.uums.server.core.dao.DAOInterface method
     */
    public List find(Object o, boolean isEqual) throws DBException {
        try {
            if (o == null) {
                String beanName = this.getClass().getName();
                beanName = beanName.substring(beanName.lastIndexOf(".") + 1);
                String hql = "from " + beanName;
                return this.getHibernateTemplate().find(hql);
            }
            if (isEqual) {
                return this.getHibernateTemplate().findByExample(o);
            } else {
                return this.findByMistiness(o);
            }
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
    }


    /**
	 * 根据ID获取对象. 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在，抛出异常。
	 */
    public <T> T get(Class<T> entityClass, Serializable id) {
		return (T) getHibernateTemplate().get(entityClass, id);
	}

   /*
     * remove
     *
     * @param id String
     * @throws DBException 通用异常
     */
     public <T> void removeById(Class<T> entityClass, Serializable id) {
		remove(get(entityClass, id));
	 }
    

    /**
     * update
     *
     * @param o Object
     * @throws DBException 通用异常
     */
    public void update(Object o) throws DBException {
        try {
            this.getHibernateTemplate().update(o);
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
    }

    public void batchUpdate(List objectList) throws DBException {
        try {
            this.getHibernateTemplate().saveOrUpdateAll(objectList);
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
    }

    public Object getByUniqueAttr(String uniqueField, String value) throws
            DBException {
        DBException dbException = new DBException("001");
        SysExceptionTool.addExceptionInfo(dbException);
        throw dbException;
    }

    /**
     * 删除
     *
     * @param o 要删除的对象
     * @throws DBException .
     */
    public void remove(Object o) throws DBException {
        try {
            List os = this.getHibernateTemplate().findByExample(o);
            getHibernateTemplate().deleteAll(os);
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
    }

    /**
     * 查询(根据HQL)
     *
     * @param hql hql
     * @return list
     * @throws DBException e
     */
    public List find(String hql) throws DBException {
        try {
            return this.getHibernateTemplate().find(hql);
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
    }

    /**
     * 查询第一条记录
     * 根据HQL
     * 此方法还不能用，有问题!
     *
     * @param hql hql
     * @return Object
     * @throws DBException e
     */
    public Object findFirstRecord(String hql) throws DBException {
        try {
            Session session = this.getHibernateTemplate().getSessionFactory().openSession();
            Query query = session.createQuery(hql);
            query.setMaxResults(1);
            Iterator iterator = query.iterate();
            if (iterator.hasNext()) {
                return iterator.next();
            }
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
        return null;
    }

    /**
     * 模糊查询
     *
     * @param o 查询的对象与条件
     * @return 返回模糊查询结果
     * @throws cn.antia.cep.db.DBException
     *          DBException
     */
    private List findByMistiness(Object o) throws DBException {
        try {
            DetachedCriteria criteria = consturctDetachedCriertia(o, false);
            if (criteria == null) return null;
            return this.getHibernateTemplate().findByCriteria(criteria);
        } catch (Exception e) {
            DBException dbException = new DBException("004",e.toString());
            SysExceptionTool.addExceptionInfo(dbException);
            throw dbException;
        }
    }

    /**
     * 构造查询器
     * 将OBJECT中的所有值取出来构造一个DetachedCriteria返回
     *
     * @param o        查询的对象与条件
     * @param isRigour 如果需要精确匹配，则传参为TRUE，否则为FALSE
     * @return 构造查询器
     * @throws cn.antia.cep.db.DBException
     *          DBException
     */
    private DetachedCriteria consturctDetachedCriertia(Object o, boolean isRigour) throws DBException {
        DetachedCriteria criteria = DetachedCriteria.forClass(o.getClass());
        Method[] methods = o.getClass().getMethods();
        if (methods == null || methods.length < 1) return criteria;
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            String methodName = method.getName();
            Class cl = method.getReturnType();
            if (methodName.indexOf("get") == 0) {
                char c = methodName.charAt(3);
                //如果第四个字符不是大写字母，则不处理
                if (c > 'a' || c < 'A') continue;
                Object value;
                String field = methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
                if (field.equals("class")) continue;
                try {
                    value = method.invoke(o, new Object[]{});
                } catch (Exception e) {
                    //如果调用出现异常，则返回为NULL
                    DBException dbException = new DBException("002",e.toString());
                    SysExceptionTool.addExceptionInfo(dbException);
                    throw dbException;
                }
                //如果这项结果值为NULL，则不处理
                if (value == null) {
                    continue;
                }
                if (isRigour) {
                    criteria.add(Expression.eq(field, value));
                } else {
                    if(cl.getName().indexOf("String") > -1){
                        //Expression.like(field, value)
                        criteria.add(Expression.like(field,value.toString(),MatchMode.ANYWHERE));
                    }else{
                        criteria.add(Expression.eq(field,value));
                    }
                }
               }
           }
           return criteria;
	   }
	}
